package models.base;

import ext.MetaKey;
import ext.jpa.UUIDModel;
import helper.GlobalConfig;
import org.apache.commons.lang.StringUtils;
import org.hibernate.annotations.Index;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;
import java.util.Date;
import java.util.List;
import java.util.function.Supplier;

/**
 * 业务对象的Key-Value属性.
 */
@Entity
@Table(name = "entity_props", schema = GlobalConfig.MIGAO_DB_SCHEMA)
@org.hibernate.annotations.Table(
        appliesTo = "entity_props",
        indexes = {
                @Index(name = "unq_entity_props_key", columnNames = {"entity_id", "prop_key"})
        }
)
public class EntityProp extends UUIDModel {

    private static final long serialVersionUID = -6750372361998062392L;

    public static final String CUSTOMFIELD = "CUSTOMFIELD";

    /**
     * 业务对象ID.
     */
    @Column(name = "entity_id", columnDefinition = "char(22)")
    public String entityId;

    /**
     * Key.
     */
    @Column(name = "prop_key", length = 50)
    public String key;

    @Column(name = "prop_value", length = 1024)
    public String value;

    /**
     * 创建时间.
     */
    @Column(name = "created_at")
    public Date createdAt;

    /**
     * 更新时间.
     */
    @Column(name = "modify_at")
    public Date modifyAt;


    public static EntityProp getByKey(String entityId, MetaKey key) {
        return getByKey(entityId, key.name());
    }
    public static EntityProp getByKey(String entityId, String key) {
        return EntityProp.find("entityId=?1 and key=?2 order by createdAt desc", entityId, key).first();
    }


    public static List<EntityProp> findAllByEntityId(String entityId) {
        return EntityProp.find("entityId=?1 order by createdAt desc", entityId).fetch();
    }


    /**
     * 设置公司属性.
     */
    public static EntityProp setKeyValue(String entityId, MetaKey key, String value) {
        return setKeyValue(entityId, key.name(), value);
    }
    public static EntityProp setKeyValue(String entityId, String key, String value) {
        EntityProp entityProp = getByKey(entityId, key);
        if (entityProp == null) {
            entityProp = new EntityProp();
            entityProp.entityId = entityId;
            entityProp.key = key;
            entityProp.createdAt = new Date();
        }

        entityProp.value = value;
        entityProp.modifyAt = new Date();
        entityProp.save();
        return entityProp;
    }

    public static void cleanKey(String entityId, MetaKey key) {
        cleanKey(entityId, key.name());
    }
    public static void cleanKey(String entityId, String key) {
        EntityProp entityProp = getByKey(entityId, key);
        if (entityProp != null) {
            entityProp.value = null;
            entityProp.modifyAt = new Date();
            entityProp.save();
        }
    }

    /**
     * 读取属性值.
     */
    public static String getKeyValue(String entityId, String key) {
        return getKeyValue(entityId, key, null);
    }
    public static String getKeyValue(String entityId, MetaKey key) {
        return getKeyValue(entityId, key, null);
    }
    public static String getKeyValue(String entityId, MetaKey key, String defaultValue) {
        return getKeyValue(entityId, key.name(), defaultValue);
    }
    public static String getKeyValue(String entityId, String key, String defaultValue) {
        EntityProp entityProp = getByKey(entityId, key);
        if (entityProp == null) {
            return defaultValue;
        }
        return entityProp.value;
    }

    /**
     * 类似缓存的方式得到指定值.
     */
    public static String getKeyValueWithSupplier(String entityId, MetaKey key, Supplier<String> supplier) {
        return getKeyValueWithSupplier(entityId, key.name(),  supplier);
    }
    public static String getKeyValueWithSupplier(String entityId, String key, Supplier<String> supplier) {
        EntityProp entityProp = getByKey(entityId, key);
        if (entityProp == null) {
            String defaultValue = supplier.get();
            if (StringUtils.isNotBlank(defaultValue)) {
                setKeyValue(entityId, key, defaultValue);
                return defaultValue;
            }
        }
        return entityProp.value;
    }

    @Override
    public String toString() {
        return "EntityProp{" +
                "id='" + id + '\'' +
                ", entityId='" + entityId + '\'' +
                ", key=" + key +
                ", value='" + value + '\'' +
                ", createdAt=" + createdAt +
                ", modifyAt=" + modifyAt +
                '}';
    }
}
